package nc.appcan.sp.bs.tool;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import nc.bs.logging.Logger;
import nc.bs.pub.filesystem.FileSystemUtil;
import nc.jdbc.framework.JdbcSession;
import nc.jdbc.framework.crossdb.CrossDBConnection;
import nc.jdbc.framework.crossdb.nativejdbc.NativeJdbcExtractorFactory;
import nc.jdbc.framework.exception.DbException;
import nc.jdbc.framework.exception.OracleException;
import nc.jdbc.framework.processor.ResultSetProcessor;
import nc.jdbc.framework.util.DBConsts;
import oracle.jdbc.OracleStatement;
import sun.misc.BASE64Encoder;

import com.microsoft.sqlserver.jdbc.SQLServerStatement;

public class NCFileDAO {
	

	private class OutNCFileDataProcessor implements ResultSetProcessor {
		private static final long serialVersionUID = 734000852517813383L;

		private String out = null;

		public OutNCFileDataProcessor() {
			super();
		}

		public String handleResultSet(ResultSet rs) throws SQLException {
			if (rs.next()) {
				InputStream in = null;
				ByteArrayOutputStream outStream = new ByteArrayOutputStream();
				try {
					if (isOracle()) {
						in = rs.getBlob(1).getBinaryStream();
					} else {
						in = rs.getBinaryStream(1);
					}
					byte []buffer = new byte[2048];
					int len = 0;
					  while( (len=in.read(buffer)) != -1){
					   outStream.write(buffer, 0, len);
					  }
					byte[] aaa =   outStream.toByteArray();
					BASE64Encoder encoder = new BASE64Encoder();
				    out = encoder.encode(aaa);
					  outStream.close();
					  in.close();
			           rs.close();
			         
				} catch (Exception e) {
					Logger.error(e.getMessage(), e);
					throw new SQLException(e.getMessage());
				} finally {
					try {
						if (in != null) {
							in.close();
						}
						if (outStream != null) {
							outStream.close();
						}
						if (rs != null) {
							rs.close();
						}
					} catch (Exception e) {
					}
				}
			} else {
			}
			return out;
		}
	}

	

	
	private String dsName = null;

	private JdbcSession session = null;

	public NCFileDAO(String dsName) {
		super();
		this.dsName = dsName;
	}

	private JdbcSession getSession() throws DbException {
		if (session == null) {
			session = new JdbcSession(dsName);
		}
		return session;
	}

	public void close() {
		if (session != null) {
			session.closeAll();
		}
	}

	private String validatePathString(String path) {
		return FileSystemUtil.validatePathString(path);

	}

public boolean isOracle() throws DbException {
		return getSession().getDbType() == DBConsts.ORACLE;
	}

	public boolean isDB2() throws DbException {
		return getSession().getDbType() == DBConsts.DB2;
	}

	private Connection getNativeConn(Connection con) throws SQLException {
		if (con instanceof CrossDBConnection) {
			con = ((CrossDBConnection) con).getPConnection();

		}
		return NativeJdbcExtractorFactory.createJdbcExtractor()
				.getNativeConnection(con);
	}

	
	public String outNCFileData(String nodePath)
			throws Exception { 
		nodePath = validatePathString(nodePath);
		String msg = null;
		String sql = "select contentdata,filelength from sm_pub_filesystem where path = ?";
		Connection con = getSession().getConnection();

		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			con = getNativeConn(con);
			ps = con.prepareStatement(sql);
			if (ps instanceof SQLServerStatement) {
				((SQLServerStatement) ps).setResponseBuffering("adaptive");
			} else if (ps instanceof OracleStatement) {
				((OracleStatement) ps).setRowPrefetch(1);
			}
			ps.setString(1, nodePath);
			rs = ps.executeQuery();
		 msg = 	new OutNCFileDataProcessor().handleResultSet(rs);
		} catch (SQLException e) {
			Logger.error(e.getMessage(), e);
			throw new OracleException(e.getMessage(), e);
		} finally {
			try {
				if (rs != null) {
					rs.close();
				}
				if (ps != null) {
					ps.close();
				}
				if (con != null) {
					con.close();
				}
				this.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return msg;
	}

}
